package com.zzp.baidu.service.impl;

import com.zzp.baidu.domain.News;
import com.zzp.baidu.domain.SearchPage;
import com.zzp.baidu.service.NewsSearchService;
import com.zzp.baidu.vo.SearchVo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.IndexBoost;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

/**
 * <p>
 * //TODO
 * NewsSearchService.java
 * </p>
 *
 * @author 佐斯特勒
 * @version v0.0.1
 * @date 2021/2/14 20:27
 * @see com.zzp.baidu.service
 **/
@Service
public class NewsSearchServiceImpl implements NewsSearchService {
    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;


    @Override
    public List<Map<String, String>> suggest(String prefix) {
        // 设置completion属性
        var tags = new CompletionSuggestionBuilder("tags")
                .prefix(prefix)
                .skipDuplicates(true);
        // 设置suggest体
        var suggestBuilder = new SuggestBuilder()
                .addSuggestion("tags_suggest", tags);
        // 匹配资源
        var sourceBuilder = new SearchSourceBuilder()
                .suggest(suggestBuilder)
                .fetchSource(new String[]{"id"}, new String[]{});
        // 查询请求
        var searchRequest = new SearchRequest("news")
                .source(sourceBuilder);
        // 查询建言
        var entries = elasticsearchRestTemplate
                .execute(client -> client.search(searchRequest, RequestOptions.DEFAULT))
                .getSuggest()
                .getSuggestion("tags_suggest")
                .getEntries();

        // 结果处理
        var results = new ArrayList<Map<String, String>>();
        entries.forEach(obj -> {
            // 仅要Complete属性的推荐
            if (obj instanceof CompletionSuggestion.Entry) {
                var entry = (CompletionSuggestion.Entry) obj;
                // 获取Options（集合），由options获取text对象
                entry.getOptions().forEach(option -> {
                    var suggestText = option.getText().toString().replace(",", " ");
                    var map = new HashMap<String, String>(8);
                    var maxLength = 20;
                    if (suggestText.length() > maxLength) {
                        suggestText = suggestText.substring(0, maxLength) + "...";
                    }
                    map.put("tag", suggestText);
                    results.add(map);
                });
            }
        });
        return results;
    }

    @Override
    public SearchVo search(SearchPage searchPage) {
        // 设置搜索条件
        var searchQueryBuilder = new NativeSearchQueryBuilder()
                .withIndicesBoost(Collections.singletonList(new IndexBoost("news", 0f)))
                .withSourceFilter(new FetchSourceFilter(new String[]{"id", "title", "url", "content"}, new String[]{}))
                .withQuery(new MultiMatchQueryBuilder(searchPage.getText(), "title", "content"))
                .withPageable(PageRequest.of(searchPage.getPager(), searchPage.getSize()))
                .withHighlightBuilder(
                        new HighlightBuilder()
                                .preTags("<font color='red'>")
                                .postTags("</font>")
                                .field("title")
                                .field("content")
                ).build();
        // 获取结果
        var search = elasticsearchRestTemplate.search(searchQueryBuilder, News.class);
        // 映射结果
        var list = search
                .stream()
                .map(s -> {
                    // 只要第一个亮词 标题
                    var title = s.getHighlightField("title").get(0);
                    // 把多个内容，链接起来
                    var content = s.getHighlightField("content")
                            .stream()
                            .reduce((u, v) -> u + "………" + v).orElse("");
                    var news = s.getContent();
                    return News.builder()
                            .id(news.getId())
                            .url(news.getUrl())
                            .title(title)
                            .content(content)
                            .build();
                }).collect(Collectors.toList());
        // 返回VO
        return SearchVo
                .builder()
                .total(search.getTotalHits())
                .contents(list)
                .build();
    }
}
